'''
Case Type： 故障&可靠性测试
Case Name： 主节点故障	sql间并行执行过程中dn主故障
Create At: 2020/07/02
@zou_jialiang0505328114
Descption:
步骤 1.启动数据库
步骤 2.开始执行dml操作
步骤 3.在执行dml操作期间，移除gaussdb，kill主进程
步骤 4.查询数据库状态
步骤 5.恢复数据库目录
步骤 6.备库切换至主库
步骤 7.查看数据库状态
步骤 8.备库重建
步骤 9.查看数据库状态
步骤 10.主备切换
步骤 11.查看数据库状态
'''
import unittest
import time
from yat.test import macro
from yat.test import Node
from testcase.utils.Common import Common
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from testcase.utils.CommonSH import *
from testcase.utils.ComThread import *


class Deletaduit(unittest.TestCase):
    sh_primy = CommonSH('PrimaryDbUser')
    sh_standby = CommonSH('Standby1DbUser')
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.log = Logger()
        self.log.info('------------Opengauss_Reliability_Dbsys_Case004.py start------------')
        self.rootNode = Node()
        self.primary_dbuser = Node(node='PrimaryDbUser')
        self.primary_root = Node(node='PrimaryRoot')
        self.standby1_root = Node(node='Standby1Root')
        self.standby1_dbuser = Node(node='Standby1DbUser')
        self.com = Common()
        self.Constant = Constant()
        self.t_name1 = 't_test1'
        self.t_name2 = 't_test2'

    def test_startdb(self):
        # 建表
        self.log.info('----------------------------创建表，并写入数据-----------------------------')

        sql = f'''
            drop table if exists {self.t_name1};
            create table {self.t_name1}(t_id integer, t_desc character(20));

            drop table if exists {self.t_name2};
            create table {self.t_name2}(t_id integer, t_desc character(20));
            '''
        self.log.info(sql)
        msg = self.sh_primy.executDbSql(sql)
        self.log.info(msg)

        insert_sql1 = f"insert into {self.t_name1} values (1,'aaa');"
        insert_sql2 = f"insert into {self.t_name2} values (1,'bbb');"
        self.log.info('开始执行dml操作')
        exec_sql_thread_1 = ComThread(self.sh_primy.cycle_exec_sql, args=(insert_sql1, 10000,))
        exec_sql_thread_2 = ComThread(self.sh_primy.cycle_exec_sql, args=(insert_sql2, 10000,))
        exec_sql_thread_1.setDaemon(True)
        exec_sql_thread_2.setDaemon(True)
        exec_sql_thread_1.start()
        exec_sql_thread_2.start()

        time.sleep(5)

        self.log.info('--------------------delete dn1-----------------------------')
        mvcmd = f"mv {macro.DB_INSTANCE_PATH} {macro.DB_INSTANCE_PATH + '.baktest'} "
        self.primary_root.sh(mvcmd)
        self.log.info(mvcmd)

        self.log.info('杀死dn主进程')
        msg = self.com.kill_pid(self.primary_root, 9)
        self.assertEqual(msg, '')

        self.log.info('查看数据库状态')
        status = self.sh_primy.getDbClusterStatus("status")
        self.log.info(status)
        self.assertFalse(status)

        self.log.info('恢复数据库目录')
        mvcmd1 = f"mv {macro.DB_INSTANCE_PATH + '.baktest'} {macro.DB_INSTANCE_PATH}"
        self.rootNode.sh(mvcmd1)
        self.log.info(mvcmd1)

        self.log.info('备库切换至主库failover')
        failover_msg = self.sh_standby.executeGsctl('failover', self.Constant.FAILOVER_SUCCESS_MSG)
        self.log.info(failover_msg)
        self.assertTrue(failover_msg)
        refreshconf_cmd = '''
                            source {source_path};                    
                            gs_om -t refreshconf'''.format(source_path=macro.DB_ENV_PATH)
        refreshMsg = self.standby1_dbuser.sh(refreshconf_cmd).result()
        self.log.info(refreshMsg)
        self.assertIn(self.Constant.REFRESHCONF_SUCCESS_MSG, refreshMsg)

        self.log.info('查看数据库状态')
        status = self.sh_primy.getDbClusterStatus('detail')
        self.log.info(status)
        self.assertIn(self.Constant.PRIMARY_NORMAL, status)

        self.log.info('备库重建')
        switch_msg = self.sh_primy.executeGsctl('build', self.Constant.REBUILD_SUCCESS_MSG, '-b full')
        self.log.info(switch_msg)
        self.assertTrue(switch_msg)

        self.log.info('查看数据库状态')
        status = self.sh_primy.getDbClusterStatus("status")
        self.log.info(status)
        self.assertTrue(status)

        self.log.info('主备切换')
        switch_msg = self.sh_primy.executeGsctl('switchover', self.Constant.SWITCH_SUCCESS_MSG)
        self.log.info(switch_msg)
        self.assertTrue(switch_msg)
        refreshconf_cmd = '''
                            source {source_path};                    
                            gs_om -t refreshconf'''.format(source_path=macro.DB_ENV_PATH)
        refreshMsg = self.primary_dbuser.sh(refreshconf_cmd).result()
        self.log.info(refreshMsg)
        self.assertIn(self.Constant.REFRESHCONF_SUCCESS_MSG, refreshMsg)

        time.sleep(20)

        self.log.info('查看数据库状态')
        status = self.sh_primy.getDbClusterStatus("status")
        self.log.info(status)
        self.assertTrue(status)

    def tearDown(self):
        self.log.info('---------this is tearDown-------')
        self.log.info('---------恢复主备关系-------')
        host_name = self.primary_root.sh('hostname').result()
        if self.sh_primy.check_whether_need_switch(host_name):
            is_switched = self.sh_primy.executeGsctl('switchover', self.Constant.SWITCH_SUCCESS_MSG)
            self.log.info(is_switched)
            refreshconf_cmd = '''
                                                source {source_path};                    
                                                gs_om -t refreshconf'''.format(source_path=macro.DB_ENV_PATH)
            refreshMsg = self.primary_dbuser.sh(refreshconf_cmd).result()
            self.log.info(refreshMsg)
        else:
            self.log.info('---------no need to switchover-------')

        # 清理环境，删除表
        msg = self.com.createLargeNumTable(self.primary_dbuser, self.t_name1, del_sign=True)
        self.log.info(msg)
        msg = self.com.createLargeNumTable(self.primary_dbuser, self.t_name2, del_sign=True)
        self.log.info(msg)

        sql = f'''drop table if exists {self.t_name1};drop table if exists {self.t_name2};'''
        self.log.info(sql)
        msg = self.sh_primy.executDbSql(sql)
        self.log.info(msg)

        db_status = self.sh_primy.getDbClusterStatus('status')
        if not db_status:
            self.log.info('恢复数据库目录')
            mvcmd1 = f"mv {macro.DB_INSTANCE_PATH + '.baktest'} {macro.DB_INSTANCE_PATH}"
            self.rootNode.sh(mvcmd1)
            self.log.info(mvcmd1)

            is_started = self.sh_primy.startDbCluster()

        else:
            pass
